#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
错误处理装饰器，用于统一处理重复的错误处理逻辑
"""
from functools import wraps
from typing import Any, Callable, TypeVar, cast

from autoapi.common.log import log

F = TypeVar('F', bound=Callable[..., Any])


def log_errors(log_message: str = "操作失败") -> Callable[[F], F]:
    """
    错误处理装饰器，统一处理异常和日志记录
    
    :param log_message: 错误日志消息
    :return: 装饰后的函数
    """
    def decorator(func: F) -> F:
        @wraps(func)
        def wrapper(*args, **kwargs) -> Any:
            try:
                result = func(*args, **kwargs)
                return result
            except Exception as e:
                log.error(f"{log_message}: {e}")
                raise e
        return cast(F, wrapper)
    return decorator


def retry_on_error(max_retries: int = 3, delay: float = 1.0) -> Callable[[F], F]:
    """
    重试装饰器，在发生错误时自动重试
    
    :param max_retries: 最大重试次数
    :param delay: 重试延迟（秒）
    :return: 装饰后的函数
    """
    def decorator(func: F) -> F:
        @wraps(func)
        def wrapper(*args, **kwargs) -> Any:
            import time
            last_exception = None
            for attempt in range(max_retries + 1):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    last_exception = e
                    if attempt < max_retries:
                        log.warning(f"操作失败，第 {attempt + 1} 次重试: {e}")
                        time.sleep(delay)
                    else:
                        log.error(f"操作失败，已达到最大重试次数 {max_retries}: {e}")
                        raise last_exception
            return None
        return cast(F, wrapper)
    return decorator


class ErrorContext:
    """
    错误处理上下文管理器
    """
    
    def __init__(self, operation_name: str, raise_error: bool = True):
        self.operation_name = operation_name
        self.raise_error = raise_error
    
    def __enter__(self):
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type is not None:
            log.error(f"{self.operation_name} 失败: {exc_val}")
            if self.raise_error:
                return False  # 重新抛出异常
            return True  # 抑制异常
        return True
